package org.vacoor.nothing.misc.express.fedex;

import com.fedex.track.stub.*;

import java.util.Calendar;

/**
 */
public abstract class FedExHelper {
    /**
     * 打印完成追踪详情
     *
     * @param ctd
     */
    public static void printCompletedTrackDetail(CompletedTrackDetail[] ctd) {
        for (int i = 0; i < ctd.length; i++) { // package detail information
            boolean cont = true;
            System.out.println("--Completed Tracking Detail--");
            if (ctd[i].getNotifications() != null) {
                System.out.println("  Completed Track Detail Notifications--");
                cont = printNotifications(ctd[i].getNotifications());
                System.out.println("  Completed Track Detail Notifications--");
            }
            if (cont) {
                print("DuplicateWayBill", ctd[i].getDuplicateWaybill());
                print("Track Details Count", ctd[i].getTrackDetailsCount());
                if (ctd[i].getMoreData()) {
                    System.out.println("  Additional package data not yet retrieved");
                    if (ctd[i].getPagingToken() != null) {
                        print("  Paging Token", ctd[i].getPagingToken());
                    }
                }
                printTrackDetail(ctd[i].getTrackDetails());
            }
            System.out.println("--Completed Tracking Detail--");
            System.out.println();
        }
    }

    /**
     * 打印追踪详情
     *
     * @param td
     */
    public static void printTrackDetail(TrackDetail[] td) {
        for (int i = 0; i < td.length; i++) {
            boolean cont = true;
            System.out.println("--Track Details--");
            if (td[i].getNotification() != null) {
                System.out.println("  Track Detail Notification--");
                cont = printNotifications(td[i].getNotification());
                System.out.println("  Track Detail Notification--");
            }
            if (cont) {
                print("Tracking Number", td[i].getTrackingNumber());
                print("Carrier code", td[i].getCarrierCode());
                if (td[i].getService() != null) {
                    if (td[i].getService().getType() != null &&
                            td[i].getService().getDescription() != null) {
                        print("Service", td[i].getService().getType());
                        print("Description", td[i].getService().getDescription());
                    }
                }
                if (td[i].getOtherIdentifiers() != null) {
                    System.out.println("--Track Package Identifer--");
                    printTrackOtherIdentifierDetail(td[i].getOtherIdentifiers());
                    System.out.println("--Track Package Identifer--");
                }
                if (td[i].getStatusDetail() != null) {
                    System.out.println("--Status Details--");
                    printStatusDetail(td[i].getStatusDetail());
                    System.out.println("--Status Details--");
                }
                if (td[i].getOriginLocationAddress() != null) {
                    System.out.println("--Origin Location--");
                    print(td[i].getOriginLocationAddress());
                    System.out.println("--Origin Location--");
                }
                if (td[i].getDestinationAddress() != null) {
                    System.out.println("--Destination Location--");
                    printDestinationInformation(td[i]);
                    System.out.println("--Destination Location--");
                }
                if (td[i].getActualDeliveryAddress() != null) {
                    System.out.println("--Delivery Address--");
                    print(td[i].getActualDeliveryAddress());
                    System.out.println("--Delivery Address--");
                }
                if (td[i].getActualDeliveryTimestamp() != null) {
                    System.out.println("Delivery Date");
                    print(td[i].getActualDeliveryTimestamp());
                }
                if (td[i].getAppointmentDeliveryTimestamp() != null) {
                    System.out.println("Appointment Date");
                    print(td[i].getAppointmentDeliveryTimestamp());
                }
                if (td[i].getCommitmentTimestamp() != null) {
                    System.out.println("Commitment Date");
                    print(td[i].getCommitmentTimestamp());
                }
                if (td[i].getDeliveryAttempts().shortValue() > 0) {
                    System.out.println("--Delivery Information--");
                    printDeliveryInformation(td[i]);
                    System.out.println("--Delivery Information--");
                }
                if (td[i].getCustomerExceptionRequests() != null) {
                    System.out.println("--Customer Exception Information--");
                    printCustomerExceptionRequests(td[i].getCustomerExceptionRequests());
                    System.out.println("--Customer Exception Information--");
                }
                if (td[i].getCharges() != null) {
                    System.out.println("--Charges--");
                    printCharges(td[i].getCharges());
                    System.out.println("--Charges--");
                }
                if (td[i].getEvents() != null) {
                    System.out.println("--Tracking Events--");
                    printTrackEvents(td[i].getEvents());
                    System.out.println("--Tracking Events--");
                }
                System.out.println("--Track Details--");
                System.out.println();
            }
        }
    }

    public static void printCustomerExceptionRequests(CustomerExceptionRequestDetail[] exceptions) {
        if (exceptions != null) {
            for (int i = 0; i < exceptions.length; i++) {
                CustomerExceptionRequestDetail exception = exceptions[i];
                print("Exception Id", exception.getId());
                print("Excpetion Status Code", exception.getStatusCode());
                print("Excpetion Status Description", exception.getStatusDescription());
                if (exception.getCreateTime() != null) {
                    System.out.println("  Customer Exception Date--");
                    print(exception.getCreateTime());
                    System.out.println("  Customer Exception Date--");
                }
            }
        }
    }

    public static void printTrackEvents(TrackEvent[] events) {
        if (events != null) {
            for (int i = 0; i < events.length; i++) {
                TrackEvent event = events[i];
                print("Event no. ", i);
                print(event.getTimestamp());
                if (event.getEventType() != null) {
                    print("Type", event.getEventType());
                }
                print("Station Id", event.getStationId());
                print("Exception Code", event.getStatusExceptionCode());
                print("", event.getStatusExceptionDescription());
                print("Description", event.getEventDescription());
                if (event.getAddress() != null) {
                    System.out.println("  Event Address--");
                    print(event.getAddress());
                    System.out.println("  Event Address--");
                }
                System.out.println();
            }
        }
    }

    public static void printStatusDetail(TrackStatusDetail tsd) {
        if (tsd != null) {
            print(tsd.getCreationTime());
            print("Code", tsd.getCode());
            if (tsd.getLocation() != null) {
                System.out.println("--Location Address Detail--");
                print(tsd.getLocation());
                System.out.println("--Location Address Detail--");
            }
            if (tsd.getAncillaryDetails() != null) {
                System.out.println("--Ancillary Details--");
                printAncillaryDetails(tsd.getAncillaryDetails());
                System.out.println("--Ancillary Details--");
            }
        }
    }

    public static void printAncillaryDetails(TrackStatusAncillaryDetail[] details) {
        if (details != null) {
            for (int i = 0; i < details.length; i++) {
                if (details[i] != null) {
                    if (details[i].getReason() != null && details[i].getReasonDescription() != null) {
                        print(details[i].getReason(), details[i].getReasonDescription());
                    }
                }
            }
        }
    }

    public static void printDestinationInformation(TrackDetail td) {
        if (td.getDestinationAddress() != null) {
            print(td.getDestinationAddress());
        }
        print("Destination Type", td.getDestinationLocationType());
        print("Service Area", td.getDestinationServiceArea());
        print("Service Area Description", td.getDestinationServiceAreaDescription());
        print("Station Id", td.getDestinationStationId());
        print("Destination Timezone Offset", td.getDestinationLocationTimeZoneOffset());
    }

    public static void printDeliveryOptionEligibility(DeliveryOptionEligibilityDetail[] options) {
        for (int i = 0; i < options.length; i++) {
            DeliveryOptionEligibilityDetail option = options[i];
            if (option != null) {
                print(option.getOption(), option.getEligibility());
            }
        }
    }

    public static void printDeliveryInformation(TrackDetail td) {
        System.out.println("Delivery attempts: " + td.getDeliveryAttempts());
        print("Delivery Location", td.getDeliveryLocationDescription());
        print("Delivery Signature", td.getDeliverySignatureName());
        if (td.getDeliveryOptionEligibilityDetails() != null) {
            System.out.println("Delivery Options");
            printDeliveryOptionEligibility(td.getDeliveryOptionEligibilityDetails());
        }
    }

    public static void printTrackOtherIdentifierDetail(TrackOtherIdentifierDetail[] id) {
        if (id != null) {
            for (int i = 0; i < id.length; i++) {
                if (id[i].getPackageIdentifier() != null) {
                    print(id[i].getPackageIdentifier().getType(),
                            id[i].getPackageIdentifier().getValue());
                }
            }
        }
    }

    public static void printTime(Calendar calendar) {
        if (calendar != null) {
            int month = calendar.get(Calendar.MONTH) + 1;
            int day = calendar.get(Calendar.DAY_OF_MONTH);
            int year = calendar.get(Calendar.YEAR);
            String date = new String(year + "-" + month + "-" + day);
            print("Date", date);
            printDOW(calendar);
        }
    }

    public static void printAddress(Address address) {
        print("__________________________________");
        if (address.getStreetLines() != null) {
            String[] streetLines = address.getStreetLines();
            for (int i = 0; i < streetLines.length; i++) {
                if (streetLines[i] != null) {
                    print("Street", streetLines[i]);

                }
            }
        }
        print("City", address.getCity());
        print("State or Province Code", address.getStateOrProvinceCode());
        print("Postal Code", address.getPostalCode());
        print("Country Code", address.getCountryCode());
        if (address.getResidential() != null) {
            if (address.getResidential()) {
                print("Address Type", "Residential");
            } else {
                print("Address Type", "Commercial");
            }
        }
        print("__________________________________");
    }

    public static void printDOW(Calendar calendar) {
        if (calendar != null) {
            String day;
            switch (calendar.get(Calendar.DAY_OF_WEEK)) {
                case 1:
                    day = "Sunday";
                    break;
                case 2:
                    day = "Monday";
                    break;
                case 3:
                    day = "Tuesday";
                    break;
                case 4:
                    day = "Wedensday";
                    break;
                case 5:
                    day = "Thursday";
                    break;
                case 6:
                    day = "Friday";
                    break;
                case 7:
                    day = "Saturday";
                    break;
                default:
                    day = "Invalid Date";
                    break;
            }
            print("Day of Week", day);
        }
    }

    public static void printCharges(TrackChargeDetail[] charges) {
        if (charges != null) {
            for (int i = 0; i < charges.length; i++) {
                print("Charge Type", charges[i].getType());
                printMoney(charges[i].getChargeAmount());
            }
        }
    }

    public static void printMoney(Money money) {
        if (money != null) {
            String currency = money.getCurrency();
            String amount = money.getAmount().toString();
            print("Charge", currency + " " + amount);
        }
    }

    public static boolean printNotifications(Object n) {
        boolean cont = true;
        if (n != null) {
            Notification[] notifications = null;
            Notification notification = null;
            if (n instanceof Notification[]) {
                notifications = (Notification[]) n;
                if (notifications == null || notifications.length == 0) {
                    System.out.println("  No notifications returned");
                }
                for (int i = 0; i < notifications.length; i++) {
                    printNotification(notifications[i]);
                    if (!success(notifications[i])) {
                        cont = false;
                    }
                }
            } else if (n instanceof Notification) {
                notification = (Notification) n;
                printNotification(notification);
                if (!success(notification)) {
                    cont = false;
                }
            }

        }
        return cont;
    }

    public static void printNotification(Notification notification) {
        if (notification == null) {
            System.out.println("null");
        }
        NotificationSeverityType nst = notification.getSeverity();

        print("  Severity", (nst == null ? "null" : nst.getValue()));
        print("  Code", notification.getCode());
        print("  Message", notification.getMessage());
        print("  Source", notification.getSource());
    }

    public static void print(Object k, Object v) {
        if (k == null || v == null) {
            return;
        }
        String key;
        String value;
        if (k instanceof String) {
            key = (String) k;
        } else {
            key = k.toString();
        }
        if (v instanceof String) {
            value = (String) v;
        } else {
            value = v.toString();
        }
        System.out.println("  " + key + ": " + value);
    }

    public static void print(Object o) {
        if (o != null) {
            if (o instanceof String) {
                System.out.println((String) o);
            } else if (o instanceof Address) {
                printAddress((Address) o);
            } else if (o instanceof Calendar) {
                printTime((Calendar) o);
            } else {
                System.out.println(o.toString());
            }

        }
    }

    public static void printWeight(String msg, Weight weight) {
        if (msg == null || weight == null) {
            return;
        }
        System.out.println(msg + ": " + weight.getValue() + " " + weight.getUnits());
    }

    public static boolean success(Notification notification) {
        Boolean cont = true;
        if (notification != null) {
            if (notification.getSeverity() == NotificationSeverityType.FAILURE ||
                    notification.getSeverity() == NotificationSeverityType.ERROR) {
                cont = false;
            }
        }

        return cont;
    }


    private FedExHelper() {
    }
}
